iT邦幫忙

2022 iThome 鐵人賽

DAY 8
0
Modern Web

前端技能樹的十萬個為什麼系列 第 8

Day 8 - 為什麼要用 Context

  • 分享至 

  • xImage
  •  

前言

在 React 元件之間,如果要傳遞資料,很直覺會想到 props,一個一個往下傳遞。但有時候考量到層級很多很深,如果一個資料要從第一層往下送到第五層,總感覺十分吃力不討好啊!

這種情況下,使用 context 是否有機會解決這個問題呢?

先想一下

  • Context 是在什麼樣的時代誕生的?
  • Context 怎麼解決問題?
  • Context 的優缺點是什麼?
  • Context 適合什麼情境?

Context 是在什麼樣的時代誕生的?

在 React 中,以元件(component)為單位組合成元件樹,而元件與元件之間若要傳遞狀態或數值,一般會使用 props 來傳遞,好處是相當直覺,像是一盆水從樹頂澆下去,水會由上往下流,也符合 React 單向資料流的概念,可以讓元件之間的關係變得簡單可預測

不過隨著元件樹愈長愈大棵,總是會有一些資料,幾乎每個元件都有它的蹤跡,比如使用者偏好、時區、app theme 等,如果透過 props 層層傳遞,這些資料就需要從 app root 的位置,不斷往下傳給其他元件,直到傳到末端的元件為止,過程可能經過數十層元件也不為過。

context

一方面程式會變得非常冗長,props 傳下去就十幾二十個參數,而且很多參數可能自己也用不到;另一方面要擔心中間有無漏傳,或者程式更新不小心動到,都需要花很多心力去維護。

Context 怎麼解決問題?

React 提出的 context 概念如下:

Context provides a way to pass data through the component tree without having to pass props down manually at every level.

白話就是,提供了另一種方式,可以不用層層傳遞,就直接送資料到目的地元件。

聽起來像是過海關可以走特別通道一樣,但其實 context 是運用了 provider 的 design pattern,透過 react.createContext() 產生 context,放在 Provider 之後,在 Provider 底下的所有元件(即 Consumer),都可以透過 useContext 來取得資料。

context2

如果說 props 像是用水澆下去,那 context 則像是打一盞燈,直接照射。

Context 的優缺點是什麼?

優點

  • 略過 props 層層傳遞的步驟,直接將資料送到指定元件

缺點

  • context 算是「元件以外」的東西,卻被放進元件內使用,因此會讓元件更難被重複利用
  • 發生變化時,會觸發 consumer 元件們重新 render,需注意是否有非預期的變化
  • 因為很多元件都可以使用,難以追溯在哪裡被更動

Context 適合什麼情境?

由於 context 發生變化時,會觸發 consumer 元件們重新 render,且難以追溯更動點,因此較適合「幾乎不更動」的資料,比如多國語系、使用者設定、theme 等,大多是「只供讀取」(readonly)的比較適合。

結語

心智圖放大版

其實 props 也不是只有單純傻傻往下傳一種方式,如果今天只是單純要將多個 props 從第一層傳到第五層,React 官方也提供了另一個 component composition 的思維,透過依賴反轉的方式,在第一層就先將這些 props 組合成一個,甚至直接組成元件,將元件當作 props 往下傳,也是一種方法。

整體來說,context 提供了一種方式,用來在跨層級的多個元件中,分享一個比較全域的資料,當然透過 context 的方式雖然方便,但也承受一些風險(如上述缺點),只要使用者善用在對的情境,缺點也不再是缺點啦~

另外,找資料的時候意外發現一個很有趣的討論,是否有想過既然 context 到處都可以用,那跟「全域變數」又有什麼差別呢?有興趣的話可以先想想,再點進去看看哦!

參考資料

React Context


上一篇
Day 7 - 為什麼要用 Redux
下一篇
Day 9 - 為什麼要用 Controlled Component
系列文
前端技能樹的十萬個為什麼30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言